{extend name="layout/plugin_layout" /}
﻿
{block name="title"}{$plugin.title} - {$app.title}{/block}
{block name="head"}
<style>
    .stats .stat {
        border-width: 1px;
        margin-top: -1px;
        margin-bottom: -1px;
    }
</style>
{/block}
{block name="main"}
<div class="container mx-auto" id="app">
    <div class="card lg:card-side bordered shadow-lg">
        <div class="card-body overflow-auto">
            <div class="main">
                <div class="alert">
                    <div class="flex-1">
                        <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="#2196f3"
                             class="w-6 h-6 mx-2">
                            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                                  d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z"></path>
                        </svg>
                        <label>注意：无法请求跨域链接</label>
                    </div>
                </div>
                <div class="form-control mt-4">
                    <label class="label">
                        <span class="label-text">下载链接</span>
                    </label>
                    <input type="text" v-model="set.input" placeholder="下载链接" class="input input-bordered">
                </div>
                <div class="form-control mt-4">
                    <label class="cursor-pointer label">
                        <span class="label-text">无限循环</span>
                        <input type="checkbox" v-model="set.infinite" class="toggle toggle-primary">
                    </label>
                </div>
                <div class="form-control">
                    <label class="label">
                        <span class="label-text">线程</span>
                    </label>
                    <div :data-tip="set.thread" class="tooltip tooltip-open mt-6">
                        <input type="range" max="32" min="1" v-model="set.thread" class="range range-primary">
                    </div>
                </div>
                <div class="card-actions mt-4">
                    <button class="btn btn-primary flex-1" @click="run">
                        {{set.status?'停止':'开始'}}
                    </button>
                </div>
                <div class="w-full shadow stats mt-4 grid-flow-row lg:grid-flow-col">
                    <div class="stat">
                        <div class="stat-figure text-primary">
                            <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24"
                                 stroke="currentColor">
                                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                                      d="M3 15a4 4 0 004 4h9a5 5 0 10-.1-9.999 5.002 5.002 0 10-9.78 2.096A4.001 4.001 0 003 15z"/>
                            </svg>
                        </div>
                        <div class="stat-title">已消失的流量</div>
                        <div class="stat-value text-primary">{{changeFilesize(waste)}}</div>
                    </div>
                    <div class="stat">
                        <div class="stat-figure text-info">
                            <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"
                                 class="inline-block w-8 h-8 stroke-current">
                                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                                      d="M13 10V3L4 14h7v7l9-11h-7z"></path>
                            </svg>
                        </div>
                        <div class="stat-title">每秒实时流量</div>
                        <div class="stat-value text-info">{{speed}}</div>
                    </div>
                    <div class="stat">
                        <div class="stat-figure text-primary">
                            <svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24"
                                 stroke="currentColor">
                                <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
                                      d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z"/>
                            </svg>
                        </div>
                        <div class="stat-title">运行时长</div>
                        <div class="stat-value">{{secToTime(spend)}}</div>
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

<script>
    var errors = null
    new Vue({
        el: '#app',
        data: {
            set: {
                input: 'https://cachefly.cachefly.net/100mb.test',
                output: '',
                infinite: true,
                status: false,
                thread: 1,
            },
            tasks: [],
            speed: '0.00B/s',
            spend: 0,
            waste: 0,
            timer: null,
            cancelSource: axios.CancelToken.source()
        },
        watch: {
            async 'set.status'(newVal) {
                if (newVal) {
                    this.cancelSource = axios.CancelToken.source()
                    this.timer = setInterval(() => {
                        this.speed = this.changeDownloadSpeed(this.tasks.reduce(function (prev, curr) {
                            return prev + curr;
                        }, 0));
                        this.spend++
                    }, 1000)
                    do {
                        await new Promise(resolve => {
                            let task = []
                            for (let i = 0; i < this.set.thread; i++) {
                                task.push(this.download(Math.random().toString(36).substr(2, 10)))
                            }
                            Promise.all(task).finally(resolve)
                        })
                    } while (this.set.status && this.set.infinite)
                    this.set.status = false
                } else {
                    this.cancelSource.cancel()
                    setTimeout(() => clearInterval(this.timer), 1000)
                }
            }
        },
        methods: {
            run() {
                this.set.status = !this.set.status
            },
            download(id) {
                let loaded = 0
                let speed = 0
                let timestamp = new Date().getTime()
                let that = this
                const index = this.tasks.push(speed) - 1
                return request({
                    url: this.set.input,
                    params: {
                        [id]: id,
                    },
                    cancelToken: this.cancelSource.token,
                    onDownloadProgress: function (progressEvent) {
                        // 处理原生进度事件
                        const now = new Date().getTime();
                        speed = (progressEvent.loaded - loaded) / (now - timestamp) * 1000
                        that.tasks[index] = speed
                        that.waste += progressEvent.loaded - loaded
                        loaded = progressEvent.loaded
                        timestamp = now
                    },
                }).catch(e => {
                    if (!axios.isCancel(e)) {
                        $message.error(e)
                        this.set.status = false
                    }
                }).finally(() => {
                    delete that.tasks[index]
                })
            },
            secToTime: (s) => {
                let t = '';
                if (s > -1) {
                    let hour = Math.floor(s / 3600)
                    let min = Math.floor(s / 60) % 60
                    let sec = s % 60
                    if (hour > 0) {
                        if (hour < 10) {
                            t += '0'
                        }
                        t = hour + "h"
                    }
                    if (hour > 0 || min > 0) {
                        if (min < 10) {
                            t += '0'
                        }
                        t += min + "m"
                    }
                    if (sec < 10) {
                        t += '0'
                    }
                    t += sec + 's'
                }
                return t
            },
            changeFilesize: (filesize) => {
                filesize = parseInt(filesize);
                let size = "";
                if (filesize === 0) {
                    size = "0.00 B"
                } else if (filesize < 1024) { //小于1KB，则转化成B
                    size = filesize.toFixed(2) + " B"
                } else if (filesize < 1024 * 1024) { //小于1MB，则转化成KB
                    size = (filesize / 1024).toFixed(2) + " KB"
                } else if (filesize < 1024 * 1024 * 1024) { //小于1GB，则转化成MB
                    size = (filesize / (1024 * 1024)).toFixed(2) + " MB"
                } else { //其他转化成GB
                    size = (filesize / (1024 * 1024 * 1024)).toFixed(2) + " GB"
                }
                return size;
            },
            changeDownloadSpeed(filesize) {
                filesize = this.changeFilesize(filesize);
                return filesize.replace(/\s([K|M|G|B]*)B{0,1}/, '$1/s')
            }
        },
    })

</script>

{/block}